package org.jeecg.modules.system.controller;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.crypto.digest.DigestUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.modules.system.entity.DeviceInfo;
import org.jeecg.modules.system.entity.OrderInfo;
import org.jeecg.modules.system.entity.SettingInfo;
import org.jeecg.modules.system.model.OrderInfoModel;
import org.jeecg.modules.system.service.IDeviceInfoService;
import org.jeecg.modules.system.service.IOrderInfoService;
import org.jeecg.modules.system.service.ISettingInfoService;
import org.jeecg.modules.system.service.IWxPayScoreService;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

@RestController
@Slf4j
@RequestMapping("/device")
public class DeviceController {

    @Resource
    private IDeviceInfoService deviceInfoService;

    @Resource
    private ISettingInfoService settingInfoService;

    @Resource
    private IOrderInfoService orderInfoService;

    @Resource
    private WxPayService wxService;

    @Resource
    private IWxPayScoreService wxPayScoreService;

    @GetMapping("/getSettingInfo")
    public Result getSettingInfo() {
        SettingInfo byId = settingInfoService.getById(1);
        return Result.OK(byId);
    }

    @PostMapping("/setting")
    public Result setting(@RequestBody SettingInfo settingInfo) {
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        if("1".equals(sysUser.getClientId())){
            BigDecimal multiply = new BigDecimal(settingInfo.getTotalFee()).multiply(new BigDecimal(100));
            settingInfo.setTotalFee(multiply.toString());
            settingInfoService.updateById(settingInfo);
            return Result.OK();
        }else{
            return Result.error("无权限");
        }

    }

    @GetMapping("/orderList/{openId}")
    public Result orderList(@PathVariable String openId,String param) {
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        LambdaQueryWrapper<OrderInfo> queryWrapper = new LambdaQueryWrapper<>();
        if(!"1".equals(sysUser.getClientId())){
            queryWrapper.eq( OrderInfo::getOpenId, openId);
        }
        if(StringUtils.isNotBlank(param)){
            queryWrapper.eq(OrderInfo::getId,param);
        }
        queryWrapper.orderByDesc(OrderInfo::getCreateTime);
        List<OrderInfo> list = orderInfoService.list(queryWrapper);
        List<OrderInfoModel> orderInfoModelList = new ArrayList<>();
        list.forEach(item -> {
            OrderInfoModel infoModel = new OrderInfoModel();
            BeanUtils.copyProperties(item, infoModel);
            DeviceInfo byId = deviceInfoService.getOne(Wrappers.<DeviceInfo>lambdaQuery()
                    .eq(DeviceInfo::getDeviceNo, item.getDeviceNo())
            );
            infoModel.setDeviceInfo(byId);
            orderInfoModelList.add(infoModel);
        });
        return Result.OK(orderInfoModelList);
    }

    @GetMapping("/status")
    public Result status() {
        List<DeviceInfo> list = deviceInfoService.list();
        JSONObject resJson = new JSONObject();
        resJson.put("total", list.size());
        //地锁状态降
        long count = list.stream().filter(item -> item.getLockState() == 2).count();
        resJson.put("useCount", count);
        SettingInfo settingInfo = settingInfoService.getById(1);
        resJson.put("settingInfo", settingInfo);
        return Result.OK(resJson);
    }

    @PostMapping("/parkingLock/callback")
    public Result parkingLockCallBack(@RequestBody JSONObject data, String appId, String sign, String datetime) {
        log.info("appId:{}", appId);
        log.info("sign:{}", sign);
        log.info("datetime:{}", datetime);
        log.info("data:{}", data.toJSONString());
        //data:{"liftType":"1","appId":"d107828479c04efd946be909a244c8e9","liftNum":"620001","parkingState":"2","liftTime":"1705299331304","lockState":"1"}
        String deviceNo = data.getString("liftNum");
        if (StringUtils.isNotBlank(deviceNo)) {
            deviceInfoService.update(Wrappers.<DeviceInfo>lambdaUpdate()
                    .eq(DeviceInfo::getDeviceNo, deviceNo)
                    .set(DeviceInfo::getParkingState, data.getString("parkingState"))
                    .set(DeviceInfo::getLockState, data.getString("lockState"))
                    .set(DeviceInfo::getOnlineState, data.getString("onlineState"))
                    .set(DeviceInfo::getLiftTime, data.getString("liftTime"))
            );
        }
        //升锁 车走了
        if("1".equals(data.getString("lockState"))){
//            DateTime dateTime = DateUtil.offsetHour(DateUtil.date(), -2);
            List<OrderInfo> list = orderInfoService.list(Wrappers.<OrderInfo>lambdaQuery()
                    .eq(OrderInfo::getDeviceNo, deviceNo)
                    .eq(OrderInfo::getState, "DOING")
                    .orderByDesc(OrderInfo::getCreateTime)
            );
//            List<OrderInfo> list = orderInfoService.list(Wrappers.<OrderInfo>lambdaQuery()
//                    .eq(OrderInfo::getDeviceNo, deviceNo)
//                    .eq(OrderInfo::getStatus, 1)
//                    .ge(OrderInfo::getCreateTime, dateTime)
//                    .orderByDesc(OrderInfo::getCreateTime)
//            );
            if (list.size() > 0) {
                OrderInfo orderInfo = list.get(0);
                wxPayScoreService.completeServiceOrder(orderInfo);
//                WxPayRefundRequest request = new WxPayRefundRequest();
//                request.setOutTradeNo(orderInfo.getOutTradeNo());
//                request.setOutRefundNo("T" + orderInfo.getOutTradeNo());
//                request.setTotalFee(Integer.valueOf(orderInfo.getTotalFee()));
//                request.setRefundFee(Integer.valueOf(orderInfo.getTotalFee()));
//                try {
//                    this.wxService.refund(request);
//                    orderInfoService.update(Wrappers.<OrderInfo>lambdaUpdate()
//                            .set(OrderInfo::getStatus, 2)
//                            .eq(OrderInfo::getOutTradeNo, orderInfo.getOutTradeNo())
//                    );
//                } catch (WxPayException e) {
//                    e.printStackTrace();
//                }
            }
        }
        return Result.OK();
    }

    @PostMapping("/parkingLockServer/event/collect")
    public Result parkingLockServerEventCallBack(@RequestBody JSONObject data, String appId, String sign, String datetime) {
        log.info("状态定时回调data:{}", data.toJSONString());
        log.info("appId:{}", appId);
        log.info("sign:{}", sign);
        log.info("datetime:{}", datetime);
        log.info("data:{}", data.toJSONString());
        //data:{"liftType":"1","appId":"d107828479c04efd946be909a244c8e9","liftNum":"620001","parkingState":"2","liftTime":"1705299331304","lockState":"1"}
        String deviceNo = data.getString("liftNum");
        if (StringUtils.isNotBlank(deviceNo)) {
            deviceInfoService.update(Wrappers.<DeviceInfo>lambdaUpdate()
                    .eq(DeviceInfo::getDeviceNo, deviceNo)
                    .set(DeviceInfo::getParkingState, data.getString("parkingState"))
                    .set(DeviceInfo::getLockState, data.getString("lockState"))
                    .set(DeviceInfo::getOnlineState, data.getString("onlineState"))
                    .set(DeviceInfo::getLiftTime, data.getString("liftTime"))
            );
        }
        //升锁 车走了
        if("1".equals(data.getString("lockState"))){
            List<OrderInfo> list = orderInfoService.list(Wrappers.<OrderInfo>lambdaQuery()
                    .eq(OrderInfo::getDeviceNo, deviceNo)
                    .eq(OrderInfo::getState, "DOING")
                    .orderByDesc(OrderInfo::getCreateTime)
            );
            if (list.size() > 0) {
                OrderInfo orderInfo = list.get(0);
                wxPayScoreService.completeServiceOrder(orderInfo);
            }
        }
        return Result.OK();
//        //{"bs":"12.4","appId":"d107828479c04efd946be909a244c8e9","ng":"0","liftNum":"620001","parkingState":"2","lockState":"1","onlineState":"1"}
//        String deviceNo = data.getString("liftNum");
//        if (StringUtils.isNotBlank(deviceNo)) {
//            deviceInfoService.update(Wrappers.<DeviceInfo>lambdaUpdate()
//                    .eq(DeviceInfo::getDeviceNo, deviceNo)
//                    .set(DeviceInfo::getParkingState, data.getString("parkingState"))
//                    .set(DeviceInfo::getLockState, data.getString("lockState"))
//                    .set(DeviceInfo::getOnlineState, data.getString("onlineState"))
//                    .set(DeviceInfo::getNg, data.getString("ng"))
//                    .set(DeviceInfo::getLiftTime, datetime)
//            );
//        }
//        if("1".equals(data.getString("lockState"))){
//            DateTime dateTime = DateUtil.offsetHour(DateUtil.date(), -2);
//            List<OrderInfo> list = orderInfoService.list(Wrappers.<OrderInfo>lambdaQuery()
//                    .eq(OrderInfo::getDeviceNo, deviceNo)
//                    .eq(OrderInfo::getStatus, 1)
//                    .ge(OrderInfo::getCreateTime, dateTime)
//                    .orderByDesc(OrderInfo::getCreateTime)
//            );
//            if (list.size() > 0) {
//                OrderInfo orderInfo = list.get(0);
//                WxPayRefundRequest request = new WxPayRefundRequest();
//                request.setOutTradeNo(orderInfo.getOutTradeNo());
//                request.setOutRefundNo("T" + orderInfo.getOutTradeNo());
//                request.setTotalFee(Integer.valueOf(orderInfo.getTotalFee()));
//                request.setRefundFee(Integer.valueOf(orderInfo.getTotalFee()));
//                try {
//                    this.wxService.refund(request);
//                    orderInfoService.update(Wrappers.<OrderInfo>lambdaUpdate()
//                            .set(OrderInfo::getStatus, 2)
//                            .eq(OrderInfo::getOutTradeNo, orderInfo.getOutTradeNo())
//                    );
//                } catch (WxPayException e) {
//                    e.printStackTrace();
//                }
//            }
//        }
//        return Result.OK();
    }

    public static void main(String[] args) {
//        String url = "http://mqtttest.dazao.online/cloud/pic/parkingLock";
//        Map<String, String> params = new HashMap<>();
//        params.put("appId", "d107828479c04efd946be909a244c8e9");
//        params.put("ip", "27.0.0.1");
//        params.put("liftNum", "620001");
//        params.put("liftType", "1");
//        params.put("timeStamp", String.valueOf(DateUtil.date().getTime()));
//        params.put("nonceStr", UUID.randomUUID().toString());
//        params.put("signType", "MD5");
//        String s = sortAndConcatenateParameters(params);
//        s += "&key=abbe80c3ab374bab8778aa5c7efa4438";
//        String encode = DigestUtil.md5Hex(s);
//        params.put("sign", encode);
//        String jsonString = JSONObject.toJSONString(params);
//        String body = HttpRequest.post(url).body(jsonString).execute().body();
//        System.out.println("body = " + body);
    }

    private static String sortAndConcatenateParameters(Map<String, String> params) {
        List<Map.Entry<String, String>> sortedParams = new ArrayList<>(params.entrySet());
        Collections.sort(sortedParams, new Comparator<Map.Entry<String, String>>() {
            @Override
            public int compare(Map.Entry<String, String> entry1, Map.Entry<String, String> entry2) {
                return entry1.getKey().compareTo(entry2.getKey());
            }
        });

        StringBuilder stringBuilder = new StringBuilder();
        for (Map.Entry<String, String> entry : sortedParams) {
            String key = entry.getKey();
            String value = entry.getValue();

            if (value != null && !value.isEmpty()) {
                if (stringBuilder.length() > 0) {
                    stringBuilder.append("&");
                }
                stringBuilder.append(key).append("=").append(value);
            }
        }

        return stringBuilder.toString();
    }
}
